angular.module('app').component('winitMindMap', {
    templateUrl: getTemplateUrl('matrix/component/tpl/winitMindMap.html'),
    bindings: {
        datas: '<',
        diagramScope: '='
    },
    controller: function ($scope, $rootScope, $element, $attrs, $timeout, lodash) {
        var ctrl = this;
        console.log("思维导图数据");
        console.log(ctrl);
        $scope.datas = ctrl.datas;
        $scope.selectNode = null;
        var $ = go.GraphObject.make; //监听模型数据的变化

        //自适应高度
        ctrl.setTableHeight = function () {
            $timeout(function () {
                var h = document.documentElement.clientHeight || document.body.clientHeight;
                h = h - 250;
                if (document.getElementById("myDiagramMindMap")) {
                    document.getElementById("myDiagramMindMap").style.height = h + "px";
                }
            })
        }
        ctrl.setTableHeight();
        window.onresize = ctrl.setTableHeight;

        myDiagram = $(go.Diagram, "myDiagramMindMap", //页面中div的id
            {
                "commandHandler.copiesTree": true,
                "commandHandler.deletesTree": true,
                "draggingTool.dragsTree": true,
                initialContentAlignment: go.Spot.Center,
                "undoManager.isEnabled": true
            }
        );

        myDiagram.addDiagramListener("Modified", function(e) {
            var button = document.getElementById("SaveButton");
            if (button) button.disabled = !myDiagram.isModified;
            var idx = document.title.indexOf("*");
            if (myDiagram.isModified) {
              if (idx < 0) document.title += "*";
            } else {
              if (idx >= 0) document.title = document.title.substr(0, idx);
            }
        });

        myDiagram.nodeTemplate = $(go.Node, "Vertical",
            { selectionObjectName: "TEXT" },
            $(go.TextBlock,
                {
                name: "TEXT",
                minSize: new go.Size(30, 15),
                editable: true
                },
                new go.Binding("text", "text").makeTwoWay(),
                new go.Binding("scale", "scale").makeTwoWay(),
                new go.Binding("font", "font").makeTwoWay()),
            $(go.Shape, "LineH",
                {
                stretch: go.GraphObject.Horizontal,
                strokeWidth: 3, height: 3,
                portId: "", fromSpot: go.Spot.LeftRightSides, toSpot: go.Spot.LeftRightSides
                },
                new go.Binding("stroke", "brush"),
                new go.Binding("fromSpot", "dir", function(d) { return spotConverter(d, true); }),
                new go.Binding("toSpot", "dir", function(d) { return spotConverter(d, false); })),
            new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
            new go.Binding("locationSpot", "dir", function(d) { return spotConverter(d, false); })
        );        

        myDiagram.nodeTemplate.selectionAdornmentTemplate = $(go.Adornment, "Spot",
            $(go.Panel, "Auto",
                $(go.Shape, { fill: null, stroke: "dodgerblue", strokeWidth: 3 }),
                $(go.Placeholder, { margin: new go.Margin(4, 4, 0, 4) })
            ),
            $("Button",
                {
                    alignment: go.Spot.Right,
                    alignmentFocus: go.Spot.Left,
                    click: addNodeAndLink 
                },
                $(go.TextBlock, "+", { font: "bold 8pt sans-serif" })
            )
        );

        myDiagram.nodeTemplate.contextMenu = $(go.Adornment, "Vertical",
            $("ContextMenuButton",
                $(go.TextBlock, "放大"),
                { 
                    click: function(e, obj) { changeTextSize(obj, 1.1); } 
                }
            ),
            $("ContextMenuButton",
                $(go.TextBlock, "缩小"),
                { 
                    click: function(e, obj) { changeTextSize(obj, 1/1.1); } 
                }
            ),
            $("ContextMenuButton",
                $(go.TextBlock, "粗体/正常"),
                { 
                    click: function(e, obj) { toggleTextWeight(obj); } 
                }
            ),
            $("ContextMenuButton",
                $(go.TextBlock, "布局"),
                {
                    click: function(e, obj) {
                        var adorn = obj.part;
                        adorn.diagram.startTransaction("Subtree Layout");
                        layoutTree(adorn.adornedPart);
                        adorn.diagram.commitTransaction("Subtree Layout");
                    }
                }
            )
        );

        myDiagram.linkTemplate = $(go.Link,
            {
                curve: go.Link.Bezier,
                fromShortLength: -2,
                toShortLength: -2,
                selectable: false
            },
            $(go.Shape,
                { strokeWidth: 3 },
                new go.Binding("stroke", "toNode", function(n) {
                    if (n.data.brush) return n.data.brush;
                    return "black";
                }).ofObject()
            )
        );

        myDiagram.contextMenu = $(go.Adornment, "Vertical",
            $("ContextMenuButton",
                $(go.TextBlock, "后一步"),
                { 
                    click: function(e, obj) { e.diagram.commandHandler.undo(); } 
                },
                new go.Binding("visible", "", function(o) { return o.diagram && o.diagram.commandHandler.canUndo(); }).ofObject()
            ),
            $("ContextMenuButton",
                $(go.TextBlock, "前一步"),
                { 
                    click: function(e, obj) { e.diagram.commandHandler.redo(); } 
                },
                new go.Binding("visible", "", function(o) { return o.diagram && o.diagram.commandHandler.canRedo(); }).ofObject()
            )
            // $("ContextMenuButton",
            //     $(go.TextBlock, "Save"),
            //     { 
            //         click: function(e, obj) { save(); } 
            //     }
            // ),
            // $("ContextMenuButton",
            //     $(go.TextBlock, "Load"),
            //     { 
            //         click: function(e, obj) { load(); } 
            //     }
            // )
        );

        myDiagram.addDiagramListener("SelectionMoved", function(e) {
            var rootX = myDiagram.findNodeForKey(0).location.x;
            myDiagram.selection.each(function(node) {
                if (node.data.parent !== 0) return; // Only consider nodes connected to the root
                var nodeX = node.location.x;
                if (rootX < nodeX && node.data.dir !== "right") {
                  updateNodeDirection(node, "right");
                } else if (rootX > nodeX && node.data.dir !== "left") {
                  updateNodeDirection(node, "left");
                }
                layoutTree(node);
            });
        });

        function spotConverter(dir, from) {
            if (dir === "left") {
                return (from ? go.Spot.Left : go.Spot.Right);
            } else {
                return (from ? go.Spot.Right : go.Spot.Left);
            }
        }
        
        function changeTextSize(obj, factor) {
            var adorn = obj.part;
            adorn.diagram.startTransaction("Change Text Size");
            var node = adorn.adornedPart;
            var tb = node.findObject("TEXT");
            tb.scale *= factor;
            adorn.diagram.commitTransaction("Change Text Size");
        }
        
        function toggleTextWeight(obj) {
            var adorn = obj.part;
            adorn.diagram.startTransaction("Change Text Weight");
            var node = adorn.adornedPart;
            var tb = node.findObject("TEXT");
            // assume "bold" is at the start of the font specifier
            var idx = tb.font.indexOf("bold");
            if (idx < 0) {
              tb.font = "bold " + tb.font;
            } else {
              tb.font = tb.font.substr(idx + 5);
            }
            adorn.diagram.commitTransaction("Change Text Weight");
        }
        
        function updateNodeDirection(node, dir) {
            myDiagram.model.setDataProperty(node.data, "dir", dir);
            // recursively update the direction of the child nodes
            var chl = node.findTreeChildrenNodes(); // gives us an iterator of the child nodes related to this particular node
            while(chl.next()) {
              updateNodeDirection(chl.value, dir);
            }
        }
        
        function addNodeAndLink(e, obj) {
            var adorn = obj.part;
            var diagram = adorn.diagram;
            diagram.startTransaction("Add Node");
            var oldnode = adorn.adornedPart;
            var olddata = oldnode.data;
            // copy the brush and direction to the new node data
            var newdata = { text: "idea", brush: olddata.brush, dir: olddata.dir, parent: olddata.key };
            diagram.model.addNodeData(newdata);
            layoutTree(oldnode);
            diagram.commitTransaction("Add Node");
        }
        
        function layoutTree(node) {
            if (node.data.key === 0) {  // adding to the root?
              layoutAll();  // lay out everything
            } else {  // otherwise lay out only the subtree starting at this parent node
              var parts = node.findTreeParts();
              layoutAngle(parts, node.data.dir === "left" ? 180 : 0);
            }
        }
        
        function layoutAngle(parts, angle) {
            var layout = go.GraphObject.make(go.TreeLayout,
                { angle: angle,
                  arrangement: go.TreeLayout.ArrangementFixedRoots,
                  nodeSpacing: 5,
                  layerSpacing: 20,
                  setsPortSpot: false, // don't set port spots since we're managing them with our spotConverter function
                  setsChildPortSpot: false });
            layout.doLayout(parts);
        }
        
        function layoutAll() {
            var root = myDiagram.findNodeForKey(0);
            if (root === null) return;
            myDiagram.startTransaction("Layout");
            // split the nodes and links into two collections
            var rightward = new go.Set(go.Part);
            var leftward = new go.Set(go.Part);
            root.findLinksConnected().each(function(link) {
                var child = link.toNode;
                if (child.data.dir === "left") {
                  leftward.add(root);  // the root node is in both collections
                  leftward.add(link);
                  leftward.addAll(child.findTreeParts());
                } else {
                  rightward.add(root);  // the root node is in both collections
                  rightward.add(link);
                  rightward.addAll(child.findTreeParts());
                }
              });
            // do one layout and then the other without moving the shared root node
            layoutAngle(rightward, 0);
            layoutAngle(leftward, 180);
            myDiagram.commitTransaction("Layout");
        }

        function save() {
            $scope.mindMapData = myDiagram.model.toJson();
            myDiagram.isModified = false;
        }

        $scope.getMindData = function() {
            $scope.mindMapData = myDiagram.model.toJson();
        }

        // 监听数据变化更新数据
        ctrl.$onChanges = function () {
            myDiagram.model = go.Model.fromJson(ctrl.datas);
            // myDiagram.model = new go.TreeModel(ctrl.datas);
        }

        //点击事件
        myDiagram.addDiagramListener("ObjectSingleClicked", function (e) {
            $scope.selectNode = e.subject.part;
            // ctrl.blur({data: e.subject.part.data});
        });

        if (ctrl.diagramScope) {
            ctrl.diagramScope = $scope;
        }
    }
});